#include<bits/stdc++.h>
using namespace std;
const int N=510;
int dis[N];//存储点前节点到生成树的最小距离
bool st[N];//代表已经进入生成树的点
int grid[N][N];
const int INF=0x3f3f3f3f;
int n,m;
int pr[N];//记录前一个节点
struct edge
{
    int u,v,w;
};

vector<edge> ans;
int ret;
bool prim()
{
    memset(dis,0x3f,sizeof(dis));//开始假设到生成树的距离无穷大
    memset(pr,-1,sizeof(pr));
    //dis[1]=0;
    for(int i=0;i<n;i++)
    {
        int t=-1;//找到距离生成树距离生成树最近的点
        for(int j=1;j<=n;j++)
        {
            if(!st[j]&&(t==-1||dis[j]<dis[t]))
            {
                t=j;
            }
        }
        //i==0第一次选择可以随便选择一个点进入生成树
        //然后跟新dis数组
        //i>=1时如果我们选择的是t此时dis值是无穷大说明没有路了直接返回代表没有生成树
        if(i&&dis[t]==INF) return false;
        //如果此时i是0代表第一次选此时为0不用加
        if(i) 
        {
            ret+=dis[t];
            ans.push_back({pr[t],t,dis[t]});
        }

        st[t]=true;
        //便利t节点的所有边
        for(int j=1;j<=n;j++)
        {
            if(dis[j]>grid[t][j])
            {
                dis[j]=grid[t][j];
                pr[j]=t;
            }
        }
    }
    return true;
}
int main()
{
    memset(grid,0x3f,sizeof(grid));
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        int u,v,w;
        cin>>u>>v>>w;
        grid[u][v]=grid[v][u]=min(grid[u][v],w);
    }
    if(prim())
    {
        cout<<ret<<endl;
        for(auto&ch:ans) cout<<ch.u<<" "<<ch.v<<" "<<ch.w<<endl;
    }
    else puts("impossible");
    return 0;
}